home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / ds3100.md / devSII.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  37KB  |  1,375 lines

  1. /* 
  2.  *  devSII.c --
  3.  *
  4.  *    The driver for the SII chip.
  5.  *
  6.  *    Copyright (C) 1989 Digital Equipment Corporation.
  7.  *    Permission to use, copy, modify, and distribute this software and
  8.  *    its documentation for any purpose and without fee is hereby granted,
  9.  *    provided that the above copyright notice appears in all copies.  
  10.  *    Digital Equipment Corporation makes no representations about the
  11.  *    suitability of this software for any purpose.  It is provided "as is"
  12.  *    without express or implied warranty.
  13.  */
  14.  
  15. #ifndef lint
  16. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/ds3100.md/devSII.c,v 9.3 91/08/19 13:55:10 jhh Exp $ SPRITE (DECWRL)";
  17. #endif not lint
  18.  
  19. #include <sprite.h>
  20. #include <sii.h>
  21. #include <mach.h>
  22. #include <dev.h>
  23. #include <devInt.h>
  24. #include <scsiHBA.h>
  25. #include <scsiDevice.h>
  26. #include <sys/scsi.h>
  27. #include <sync.h>
  28. #include <stdlib.h>
  29. #include <user/fs.h>
  30.  
  31. #define RESET TRUE
  32.  
  33. /* 
  34.  * MACROS for timing out spin loops.
  35.  *
  36.  *    Waits while expression is true.
  37.  *
  38.  *    args:    expr         - expression to spin on
  39.  *        spincount     - amount of time to wait in microseconds
  40.  *        retval        - return value of this macro
  41.  */
  42. #define    SII_WAIT_WHILE(expr,spincount,retval) {                \
  43.         for (retval = 0; ((retval < 100) && (expr)); retval++) {\
  44.         }                            \
  45.         while ((expr) && ( retval < spincount)) {        \
  46.             MACH_DELAY(100);                \
  47.             retval++;                    \
  48.         }                            \
  49.     }
  50.  
  51. /*
  52.  *     Waits unitl expression is true.
  53.  */
  54. #define SII_WAIT_UNTIL(expr,spincount,retval) {                \
  55.         SII_WAIT_WHILE(!(expr),spincount,retval);        \
  56.     }
  57.  
  58. /*
  59.  * The different phases.
  60.  */
  61. #define MSG_IN_PHASE    0x7
  62. #define MSG_OUT_PHASE    0x6
  63. #define STATUS_PHASE    0x3
  64. #define CMD_PHASE    0x2
  65. #define DATA_IN_PHASE    0x1
  66. #define DATA_OUT_PHASE    0x0
  67.  
  68. /*
  69.  * Forward declaration. 
  70.  */
  71. typedef struct Controller Controller;
  72.  
  73. /*
  74.  * Device - The data structure containing information about a device. One of
  75.  * these structure is kept for each attached device. Note that is structure
  76.  * is casted into a ScsiDevice and returned to higher level software.
  77.  * This implies that the ScsiDevice must be the first field in this
  78.  * structure.
  79.  */
  80.  
  81. typedef struct Device {
  82.     ScsiDevice    handle;    /* Scsi Device handle. This is the only part
  83.              * of this structure visible to higher 
  84.              * level software. MUST BE FIRST FIELD IN STRUCTURE. */
  85.     int        targetID;/* SCSI Target ID of this device. Note that
  86.               * the LUN is store in the device handle. */
  87.     Controller    *ctrlPtr;/* Controller to which device is attached. */
  88.            /*
  89.             * The following part of this structure is 
  90.             * used to handle SCSI commands that return 
  91.             * CHECK status. To handle the REQUEST SENSE
  92.             * command we must: 1) Save the state of the current
  93.             * command into the "struct FrozenCommand". 2) Submit
  94.             * a request sense command formatted in SenseCmd
  95.             * to the device.
  96.             */
  97.     unsigned    buffOffset;
  98.     struct FrozenCommand {               
  99.     ScsiCmd    *scsiCmdPtr;       /* The frozen command. */
  100.     unsigned char statusByte; /* It's SCSI status byte, Will always have
  101.                    * the check bit set.
  102.                    */
  103.     int amountTransferred;    /* Number of bytes transferred by this 
  104.                    * command.
  105.                    */
  106.     int status;          /* Status of frozen command. */
  107.     } frozen;    
  108.     char senseBuffer[DEV_MAX_SENSE_BYTES]; /* Data buffer for request sense */
  109.     ScsiCmd        SenseCmd;         /* Request sense command buffer. */
  110. } Device;
  111.  
  112. /*
  113.  * Controller - The Data structure describing an SII controller.
  114.  */
  115. struct Controller {
  116.     volatile SIIRegs *regsPtr; /* Pointer to the registers of this controller.*/
  117.     int        dmaState;    /* DMA state for this controller, defined below. */
  118.     Boolean dmaStarted; /* TRUE => dma was started. */
  119.     char    *name;    /* String for error message for this controller.  */
  120.     DevCtrlQueues devQueues;    /* Device queues for devices attached to this
  121.                  * controller.     */
  122.     Address    ramBuff;    /* DMA memory. */
  123.     Sync_Semaphore mutex; /* Lock protecting controller's data structures. */
  124.               /* Until disconnect/reconnect is added we can have
  125.                * only one current active device and scsi command.*/
  126.     Device     *devPtr;       /* Current active command. */
  127.     ScsiCmd   *scsiCmdPtr; /* Current active command. */
  128.     Device  *devicePtr[8][8]; /* Pointers to the device attached to the 
  129.                    * controller index by [targetID][LUN].
  130.                    * NIL if device not attached yet. Zero if
  131.                    * device conflicts with HBA address.  */
  132. };
  133.  
  134. /*
  135.  * Possible values for the dmaState state field of a controller.
  136.  *
  137.  * DMA_RECEIVE  - data is being received from the device, such as on
  138.  *    a read, inquiry, or request sense.
  139.  * DMA_SEND     - data is being send to the device, such as on a write.
  140.  * DMA_INACTIVE - no data needs to be transferred.
  141.  */
  142.  
  143. #define DMA_RECEIVE 0
  144. #define    DMA_SEND 1
  145. #define    DMA_INACTIVE 2
  146.  
  147.  
  148. /*
  149.  * MAX_SII_CTRLS - Maximum number of SII controllers attached to the
  150.  *             system.
  151.  */
  152. #define    MAX_SII_CTRLS    1
  153. static Controller *controllers[MAX_SII_CTRLS];
  154.  
  155. /*
  156.  * Highest number controller we have probed for.
  157.  */
  158. static int numSIIControllers = 0;
  159.  
  160. int devSIIDebug = 1;
  161.  
  162. /*
  163.  * Forward declarations.  
  164.  */
  165.  
  166. static void        Reset();
  167. static ReturnStatus    SendCommand();
  168. static ReturnStatus    GetStatusByte();
  169. static ReturnStatus    WaitPhase();
  170. static ReturnStatus     RecvBytes();
  171. static void         PrintRegs();
  172. static ReturnStatus     StartDMA();
  173. static char        *PhaseName();
  174.  
  175.  
  176. /*
  177.  *----------------------------------------------------------------------
  178.  *
  179.  * Reset --
  180.  *
  181.  *    Reset a SCSI bus controlled by the SII.
  182.  *
  183.  * Results:
  184.  *    None.
  185.  *
  186.  * Side effects:
  187.  *    Reset the controller and SCSI bus.
  188.  *
  189.  *----------------------------------------------------------------------
  190.  */
  191. static void
  192. Reset(ctrlPtr)
  193.     Controller *ctrlPtr;
  194. {
  195.     volatile SIIRegs *regsPtr = ctrlPtr->regsPtr;
  196.  
  197.     /*
  198.      * Reset the SII chip.
  199.      */
  200.     regsPtr->comm = SII_CHRESET;
  201.     /*
  202.      * Set arbitrated bus mode.
  203.      */
  204.     regsPtr->csr = SII_HPM;
  205.     /*
  206.      * SII is always ID 7.
  207.      */
  208.     regsPtr->id = SII_ID_IO | 7;
  209.     /*
  210.      * Enable SII to drive SCSI bus and turn off synchronous commands.
  211.      */
  212.     regsPtr->dictrl = SII_PRE;
  213.     regsPtr->dmctrl = 0;
  214.     /*
  215.      * Assert SCSI bus reset for at least 25 Usec to clear the 
  216.      * world. SII_RST is self clearing.
  217.      */
  218.     regsPtr->comm = SII_RST;
  219.     MACH_DELAY(25);
  220.     /*
  221.      * Clear any pending interrupts from the reset.
  222.      */
  223.     regsPtr->cstat = regsPtr->cstat;
  224.     regsPtr->dstat = regsPtr->dstat;
  225.     /*
  226.      * Set up SII for arbitrated bus mode, SCSI parity checking,
  227.      * Select Enable, Reselect Enable, and Interrupt Enable.
  228.      */
  229.     regsPtr->csr = (SII_HPM | SII_RSE | SII_SLE | SII_PCE | SII_IE);
  230.     MACH_DELAY(5 * 1000000);
  231. }
  232.  
  233.  
  234. /*
  235.  *----------------------------------------------------------------------
  236.  *
  237.  * SelectTarget --
  238.  *
  239.  *      Select a target.
  240.  *
  241.  * Results:
  242.  *    SUCCESS if could select, FAILURE if couldn't.
  243.  *
  244.  * Side effects:
  245.  *    None.
  246.  *
  247.  *----------------------------------------------------------------------
  248.  */
  249. ReturnStatus
  250. SelectTarget(devPtr)
  251.     Device    *devPtr;    /* Device we want to select target for. */
  252. {
  253.     volatile register SIIRegs *regsPtr;    
  254.     int retval, i;
  255.  
  256.     regsPtr = devPtr->ctrlPtr->regsPtr;
  257.  
  258.     /* Loop till retries exhausted */
  259.     for(i=0; i < 2; i++) {
  260.         regsPtr->slcsr = devPtr->targetID;
  261.         regsPtr->comm = SII_SELECT;
  262.     Mach_EmptyWriteBuffer();
  263.  
  264.         /* 
  265.      * Start timer to wait for a select to occur
  266.      */
  267.         SII_WAIT_UNTIL(regsPtr->cstat & SII_SCH, SII_WAIT_COUNT/4, retval);
  268.  
  269.     /* 
  270.      * If a state change did occur then make sure we are connected
  271.      */
  272.     if((regsPtr->cstat & SII_SCH) && !(regsPtr->cstat & SII_CON)) {
  273.             SII_WAIT_UNTIL((regsPtr->cstat & SII_CON),SII_WAIT_COUNT,retval);
  274.     }
  275.  
  276.     if(retval >= SII_WAIT_COUNT || !(regsPtr->cstat & SII_CON)) {
  277.         regsPtr->cstat = SII_SCH;
  278.         Mach_EmptyWriteBuffer();
  279.         continue;
  280.         }
  281.  
  282.     regsPtr->cstat = SII_SCH;
  283.     Mach_EmptyWriteBuffer();
  284.     return(SUCCESS);
  285.     }
  286.     /* 
  287.      * Selection failed, clear all bus signals
  288.      */
  289.     if (devSIIDebug > 0) {
  290.     printf("SelectTarget: Couldn't select target %d\n", devPtr->targetID);
  291.     }
  292.     if (devSIIDebug > 4) {
  293.     printf("Cstat = 0x%x\n", regsPtr->cstat);
  294.     }
  295.     regsPtr->cstat = SII_SCH;
  296.     regsPtr->comm = SII_DISCON;
  297.     Mach_EmptyWriteBuffer();
  298.     SII_WAIT_UNTIL((regsPtr->cstat & SII_SCH), SII_WAIT_COUNT, retval);
  299.     regsPtr->cstat = 0xffff;
  300.     regsPtr->dstat = 0xffff;
  301.     regsPtr->comm = 0;
  302.     Mach_EmptyWriteBuffer();
  303.     return(FAILURE);
  304. }
  305.  
  306.  
  307. /*
  308.  *----------------------------------------------------------------------
  309.  *
  310.  * SendCommand --
  311.  *
  312.  *      Send a command to a SCSI controller via the SII.
  313.  *
  314.  *    NOTE: The caller is assumed to have the master lock of the controller
  315.  *    to which the device is attached held.
  316.  *
  317.  *    NOTE2: We are always called with the master lock down so we don't
  318.  *           have to worry about interrupts jumping in at the wrong time.
  319.  *
  320.  * Results:
  321.  *    An error code.
  322.  *
  323.  * Side effects:
  324.  *    Those of the command (Read, write etc.)
  325.  *
  326.  *----------------------------------------------------------------------
  327.  */
  328. static ReturnStatus
  329. SendCommand(devPtr, scsiCmdPtr)
  330.     Device     *devPtr;        /* Device to sent to. */
  331.     ScsiCmd    *scsiCmdPtr;        /* Command to send. */
  332. {
  333.     ReturnStatus        status;
  334.     register char        *charPtr;
  335.     Controller            *ctrlPtr;
  336.     int                size;
  337.     Address             addr;    
  338.  
  339.     /*
  340.      * Set current active device and command for this controller.
  341.      */
  342.     ctrlPtr = devPtr->ctrlPtr;
  343.     ctrlPtr->scsiCmdPtr = scsiCmdPtr;
  344.     ctrlPtr->devPtr = devPtr;
  345.     size = scsiCmdPtr->bufferLen;
  346.     addr = scsiCmdPtr->buffer;
  347.     /*
  348.      * Determine the DMA state the size and direction of data transfer.
  349.      */
  350.     if (size == 0) {
  351.     ctrlPtr->dmaState = DMA_INACTIVE;
  352.     } else {
  353.     ctrlPtr->dmaState = (scsiCmdPtr->dataToDevice) ? DMA_SEND :
  354.                              DMA_RECEIVE;
  355.     }
  356.     ctrlPtr->dmaStarted = FALSE;
  357.  
  358.     if (devSIIDebug > 3) {
  359.     printf("SIICommand: %s cmd 0x%x addr %x size %d dma %s\n",
  360.         devPtr->handle.locationName, scsiCmdPtr->commandBlock[0], addr,
  361.         size, (ctrlPtr->dmaState == DMA_INACTIVE) ? "not active" :
  362.         ((ctrlPtr->dmaState == DMA_SEND) ? "send" :
  363.                               "receive"));
  364.     }
  365.  
  366.     status = SelectTarget(devPtr);
  367.     if (status != SUCCESS) { 
  368.     return(status);
  369.     }
  370.  
  371.     if (devSIIDebug > 5) {
  372.     printf("SIICommand: %s waiting for command phase.\n",
  373.         devPtr->handle.locationName);
  374.     }
  375.     status = WaitPhase(ctrlPtr, CMD_PHASE, RESET);
  376.     if (status != SUCCESS) {
  377.     if (devSIIDebug > 0) {
  378.         printf("SII: wait on CMD_PHASE failed.\n");
  379.     }
  380.     return(status);
  381.     }
  382.     /*
  383.      * Stuff the control block through the commandStatus register.
  384.      */
  385.     if (devSIIDebug > 5) {
  386.     printf("SCSI3Command: %s stuffing command of %d bytes.\n", 
  387.         devPtr->handle.locationName, scsiCmdPtr->commandBlockLen);
  388.     }
  389.     charPtr = scsiCmdPtr->commandBlock;
  390.  
  391.     if((unsigned char)charPtr & 0x1) {
  392.     panic("SendCommand: Misaligned scsi command\n");
  393.     }
  394.     status = StartDMA(ctrlPtr, DMA_SEND, TRUE, scsiCmdPtr->commandBlockLen, 
  395.             charPtr);
  396.     return status;
  397. }
  398.  
  399.  
  400. /*
  401.  *----------------------------------------------------------------------
  402.  *
  403.  * StartDMA --
  404.  *
  405.  *    Issue the sequence of commands to the controller to start DMA.
  406.  *    If the wait parameter is TRUE then this procedure will wait 
  407.  *    until the DMA is finished and copy the results into the
  408.  *    buffer. Otherwise it will just return and whoever handles the
  409.  *    DMA interrupt will have to copy the data.
  410.  *
  411.  *    NOTE: the data buffer should be word-aligned for DMA out.
  412.  *
  413.  * Results:
  414.  *    SUCCESS if DMA was started (and possibly finished) correctly.
  415.  *    DEV_TIMEOUT if we timed out waiting for the DMA to finish.
  416.  *
  417.  * Side effects:
  418.  *    DMA is enabled.  No registers other than the control register are
  419.  *    to be accessed until DMA is disabled again.
  420.  *
  421.  *----------------------------------------------------------------------
  422.  */
  423. static ReturnStatus
  424. StartDMA(ctrlPtr, direction, wait, size, buffer)
  425.     register Controller *ctrlPtr;    /* Controller */
  426.     Boolean        wait;        /* TRUE => wait for DMA to complete. */
  427.     int            direction;    /* DMA_SEND or DMA_RECEIVE. */
  428.     int            size;        /* # of bytes to transfer. */
  429.     char        *buffer;    /* Data buffer. */
  430. {
  431.     volatile register SIIRegs    *regsPtr;
  432.     register Device        *devPtr;
  433.     unsigned short        tmpPhase;
  434.     unsigned short        tmpState;
  435.  
  436.     devPtr = ctrlPtr->devPtr;
  437.  
  438.     if (devSIIDebug > 4) {
  439.     printf("%s: StartDMA %s called size = %d.\n", ctrlPtr->name,
  440.         (direction == DMA_RECEIVE) ? "receive" :
  441.         ((direction == DMA_SEND) ? "send" :
  442.                           "not-active!"), size);
  443.     }
  444.     regsPtr = ctrlPtr->regsPtr;
  445.     regsPtr->comm &= ~(SII_INXFER | SII_DMA);
  446.     regsPtr->dstat = SII_DNE;
  447.     Mach_EmptyWriteBuffer();
  448.     if (direction == DMA_SEND) {
  449.     CopyToBuffer((unsigned short *)buffer, 
  450.              (unsigned short *)(ctrlPtr->ramBuff + devPtr->buffOffset),
  451.              size);
  452.     Mach_EmptyWriteBuffer();
  453.     }
  454.     regsPtr->dmaddrl = devPtr->buffOffset & 0x00ffffff;
  455.     regsPtr->dmaddrh = (devPtr->buffOffset & 0x00ffffff) >> 16;
  456.     regsPtr->dmlotc = size;
  457.     Mach_EmptyWriteBuffer();
  458.     tmpPhase = regsPtr->dstat & SII_PHA_MSK;
  459.     tmpState = regsPtr->cstat & SII_STATE_MSK;
  460.     if (devSIIDebug > 4) {
  461.     printf("StartDMA: dstat is 0x%x.\n", regsPtr->dstat);
  462.     printf("StartDMA: cstat is 0x%x.\n", regsPtr->cstat);
  463.     printf("StartDMA: setting comm to 0x%x.\n", 
  464.         SII_DMA | SII_INXFER | tmpState | tmpPhase);
  465.     }
  466.     regsPtr->comm = SII_DMA | SII_INXFER | tmpState | tmpPhase;
  467.     Mach_EmptyWriteBuffer();
  468.  
  469.     if (wait) {
  470.     int    retval;
  471.  
  472.     /*
  473.      * Wait for the DMA to complete.
  474.      */
  475.     SII_WAIT_UNTIL((regsPtr->dstat & SII_DNE), SII_WAIT_COUNT, retval);
  476.     regsPtr->comm &= ~(SII_INXFER | SII_DMA);
  477.     if (!(regsPtr->dstat & SII_DNE)) {
  478.         printf("StartDMA: DMA failed\n");
  479.     }
  480.     if (retval >= SII_WAIT_COUNT) {
  481.         return (DEV_TIMEOUT);
  482.     }
  483.     regsPtr->dstat = SII_DNE;
  484.     regsPtr->dmlotc = 0;
  485.     Mach_EmptyWriteBuffer();
  486.     if (direction == DMA_RECEIVE) {
  487.         CopyFromBuffer(
  488.         (unsigned short *)(ctrlPtr->ramBuff+devPtr->buffOffset),
  489.             (unsigned char *) buffer, size);
  490.     }
  491.     } else {
  492.     ctrlPtr->dmaStarted = TRUE;
  493.     }
  494.     return (SUCCESS);
  495. }
  496.  
  497.  
  498. /*
  499.  *----------------------------------------------------------------------
  500.  *
  501.  * GetStatusByte --
  502.  *
  503.  *    Complete an SCSI command by getting the status bytes from
  504.  *    the device and waiting for the ``command complete''
  505.  *    message that follows the status bytes.  
  506.  *
  507.  * Results:
  508.  *    An error code if the status didn't come through or it
  509.  *    indicated an error.
  510.  *
  511.  * Side effects:
  512.  *    None.
  513.  *
  514.  *----------------------------------------------------------------------
  515.  */
  516. static ReturnStatus
  517. GetStatusByte(ctrlPtr,statusBytePtr)
  518.     Controller *ctrlPtr;        /* Controller to get byte from. */
  519.     unsigned char *statusBytePtr;    /* Where to put the status byte. */
  520. {
  521.     ReturnStatus        status;
  522.     char            message;
  523.  
  524.     if (devSIIDebug > 4) {
  525.     printf("GetStatusByte called ");
  526.     }
  527.     *statusBytePtr = 0;
  528.  
  529.     /*
  530.      * After the DATA_IN/OUT phase we enter the STATUS phase for
  531.      * 1 byte (usually) of status.  This is followed by the MESSAGE phase
  532.      */
  533.     status = WaitPhase(ctrlPtr, STATUS_PHASE, RESET);
  534.     if (status != SUCCESS) {
  535.     if (devSIIDebug > 3) {
  536.         printf("Warning: %s wait on PHASE_STATUS failed.\n",ctrlPtr->name);
  537.     }
  538.     return(status);
  539.     }
  540.     /*
  541.      * Get one status byte.
  542.      */
  543.     status = StartDMA(ctrlPtr, DMA_RECEIVE, TRUE, 1, (char *)statusBytePtr);
  544.     if (status != SUCCESS) {
  545.     printf("Warning: %s error 0x%x getting status byte\n", 
  546.         ctrlPtr->name, status);
  547.     return (status);
  548.     }
  549.     if (devSIIDebug > 4) {
  550.     printf("got 0x%x\n", *statusBytePtr);
  551.     }
  552.     /*
  553.      * Wait for the message in phase and grab the COMMAND COMPLETE message
  554.      * off the bus.
  555.      */
  556.     status = WaitPhase(ctrlPtr, MSG_IN_PHASE, RESET);
  557.     if (status != SUCCESS) {
  558.         printf("Warning: %s wait on PHASE_MSG_IN after status failed.\n",
  559.         ctrlPtr->name);
  560.     return(status);
  561.     } 
  562.     status = StartDMA(ctrlPtr, DMA_RECEIVE, TRUE, 1, &message);
  563.     if (status != SUCCESS) {
  564.     printf("Warning: %s got error 0x%x getting message and status.\n",
  565.                  ctrlPtr->name, status);
  566.     return(status);
  567.     }
  568.     if (message != SCSI_COMMAND_COMPLETE) {
  569.     printf("Warning: %s message %d after status is not command complete.\n",        ctrlPtr->name, message);
  570.     return(FAILURE);
  571.     }
  572.     if (devSIIDebug > 4) {
  573.     printf("Got message 0x%x\n", message);
  574.     }
  575.     return(SUCCESS);
  576. }
  577.  
  578.  
  579. #define    WAIT_LENGTH        500000
  580.  
  581.  
  582. /*
  583.  *----------------------------------------------------------------------
  584.  *
  585.  * WaitPhase --
  586.  *
  587.  *    Wait for a phase to be signalled in the controller registers.
  588.  *     This is a specialized version of WaitReg, which compares
  589.  *     all the phase bits to make sure the phase is exactly what is
  590.  *    requested and not something that matches only in some bits.
  591.  *
  592.  * Results:
  593.  *    SUCCESS if the condition occurred before a threshold time limit,
  594.  *    DEV_TIMEOUT otherwise.
  595.  *
  596.  * Side effects:
  597.  *    This resets the SCSI bus if the condition bits are not set by
  598.  *    the controller before timeout.
  599.  *
  600.  *----------------------------------------------------------------------
  601.  */
  602. static ReturnStatus
  603. WaitPhase(ctrlPtr, phase, reset)
  604.     Controller *ctrlPtr;    /* Controller state */
  605.     unsigned char phase;    /* phase to check */
  606.     Boolean reset;        /* whether to reset the bus on error */
  607. {
  608.     volatile register SIIRegs    *regsPtr = (SIIRegs *)ctrlPtr->regsPtr;
  609.     register int        i;
  610.     ReturnStatus        status = DEV_TIMEOUT;
  611.     register unsigned short    dstatReg;
  612.  
  613.     for (i=0 ; i < WAIT_LENGTH ; i++) {
  614.     dstatReg = regsPtr->dstat;
  615.     if (devSIIDebug > 10 && i < 5) {
  616.         printf("%d/%x ", i, dstatReg);
  617.     }
  618.     if ((dstatReg & SII_PHA_MSK) == phase) {
  619.         return(SUCCESS);
  620.     }
  621.     }
  622.     if (devSIIDebug > 5) {
  623.     printf("WaitPhase: timed out.\n");
  624.     PrintRegs(regsPtr);
  625.     printf("WaitPhase: was checking for phase 0x%x.\n",
  626.            (int) phase);
  627.     printf("WaitPhase: dstat is 0x%x.\n", dstatReg);
  628.     }
  629.     if (reset) {
  630.     Reset(ctrlPtr);
  631.     }
  632.     return(status);
  633. }
  634.  
  635.  
  636. /*
  637.  *----------------------------------------------------------------------
  638.  *
  639.  * PrintRegs --
  640.  *
  641.  *    Print out the interesting registers.  This could be a macro but
  642.  *    then it couldn't be called from kdbx.  This routine is necessary
  643.  *    because kdbx doesn't print all the character values properly.
  644.  *
  645.  * Results:
  646.  *    None.
  647.  *
  648.  * Side effects:
  649.  *    Data is displayed on the console or to the debugger.
  650.  *
  651.  *----------------------------------------------------------------------
  652.  */
  653. /*ARGSUSED*/
  654. static void
  655. PrintRegs(regsPtr)
  656.     volatile    SIIRegs *regsPtr;
  657. {
  658. }
  659.  
  660.  
  661. /*
  662.  *----------------------------------------------------------------------
  663.  *
  664.  *  SpecialSenseProc --
  665.  *
  666.  *    Special function used for HBA generated REQUEST SENSE. A SCSI
  667.  *    command request with this function as a call back proc will
  668.  *    be processed by routine RequestDone as a result of a 
  669.  *    REQUEST SENSE. This routine is never called.
  670.  *
  671.  * Results:
  672.  *    None.
  673.  *
  674.  * Side effects:
  675.  *    None.
  676.  *
  677.  *----------------------------------------------------------------------
  678.  */
  679.  
  680. static int
  681. SpecialSenseProc()
  682. {
  683. }
  684.  
  685.  
  686. /*
  687.  *----------------------------------------------------------------------
  688.  *
  689.  * RequestDone --
  690.  *
  691.  *    Process a request that has finished. Unless a SCSI check condition
  692.  *    bit is present in the status returned, the request call back
  693.  *    function is called.  If check condition is set we fire off a
  694.  *    SCSI REQUEST SENSE to get the error sense bytes from the device.
  695.  *
  696.  * Results:
  697.  *    None.
  698.  *
  699.  * Side effects:
  700.  *    The call back function may be called.
  701.  *
  702.  *----------------------------------------------------------------------
  703.  */
  704.  
  705. void
  706. RequestDone(devPtr, scsiCmdPtr, status, scsiStatusByte, amountTransferred)
  707.     Device        *devPtr;        /* Device for request. */
  708.     ScsiCmd        *scsiCmdPtr;        /* Request that finished. */
  709.     ReturnStatus    status;            /* Status returned. */
  710.     unsigned char    scsiStatusByte;        /* SCSI Status Byte. */
  711.     int            amountTransferred;    /* Amount transferred by
  712.                          * command. */
  713. {
  714.     ReturnStatus    senseStatus;
  715.     Controller            *ctrlPtr = devPtr->ctrlPtr;
  716.  
  717.  
  718.     if (devSIIDebug > 3) {
  719.     printf("RequestDone for %s status 0x%x scsistatus 0x%x count %d\n",
  720.         devPtr->handle.locationName, status,scsiStatusByte,
  721.         amountTransferred);
  722.     }
  723.     /*
  724.      * First check to see if this is the reponse of a HBA generated 
  725.      * REQUEST SENSE command.  If this is the case, we can process
  726.      * the callback of the frozen command for this device and
  727.      * allow the flow of command to the device to be resummed.
  728.      */
  729.     if (scsiCmdPtr->doneProc == SpecialSenseProc) {
  730.     (devPtr->frozen.scsiCmdPtr->doneProc)(devPtr->frozen.scsiCmdPtr, 
  731.             devPtr->frozen.status,
  732.             devPtr->frozen.statusByte, 
  733.             devPtr->frozen.amountTransferred,
  734.             amountTransferred,
  735.             devPtr->senseBuffer);
  736.      ctrlPtr->scsiCmdPtr = (ScsiCmd *)NIL;
  737.      return;
  738.     }
  739.     /*
  740.      * This must be an outside request finishing. If the request 
  741.      * suffered an error or the HBA or the scsi status byte
  742.      * says there is no error sense present, we can do the
  743.      * callback and free the controller.
  744.      */
  745.     if ((status != SUCCESS) || !SCSI_CHECK_STATUS(scsiStatusByte)) {
  746.     (scsiCmdPtr->doneProc)(scsiCmdPtr, status, scsiStatusByte,
  747.                    amountTransferred, 0, (char *) 0);
  748.      ctrlPtr->scsiCmdPtr = (ScsiCmd *) NIL;
  749.      return;
  750.    } 
  751.    if (status != SUCCESS) {
  752.        amountTransferred = 0;
  753.    }
  754.    /*
  755.     * If we got here than the SCSI command came back from the device
  756.     * with the CHECK bit set in the status byte.
  757.     * Need to perform a REQUEST SENSE. Move the current request 
  758.     * into the frozen state and issue a REQUEST SENSE. 
  759.     */
  760.    MASTER_LOCK(&(ctrlPtr->mutex));
  761.    devPtr->frozen.scsiCmdPtr = scsiCmdPtr;
  762.    devPtr->frozen.statusByte = scsiStatusByte;
  763.    devPtr->frozen.amountTransferred = amountTransferred;
  764.    devPtr->frozen.status = status;
  765.    DevScsiSenseCmd((ScsiDevice *)devPtr, DEV_MAX_SENSE_BYTES, 
  766.            devPtr->senseBuffer, &(devPtr->SenseCmd));
  767.    devPtr->SenseCmd.doneProc = SpecialSenseProc,
  768.    senseStatus = SendCommand(devPtr, &(devPtr->SenseCmd));
  769.    MASTER_UNLOCK(&(ctrlPtr->mutex));
  770.    /*
  771.     * If we got an HBA error on the REQUEST SENSE we end the outside 
  772.     * command with the SUCCESS status but zero sense bytes returned.
  773.     */
  774.    if (senseStatus != SUCCESS) {
  775.     (scsiCmdPtr->doneProc)(scsiCmdPtr, status, scsiStatusByte,
  776.                    amountTransferred, 0, (char *) 0);
  777.     ctrlPtr->scsiCmdPtr = (ScsiCmd *) NIL;
  778.    }
  779.  
  780. }
  781.  
  782. /*
  783.  *----------------------------------------------------------------------
  784.  *
  785.  * entryAvailProc --
  786.  *
  787.  *    Act upon an entry becomming available in the queue for this
  788.  *    controller. This routine is the Dev_Queue callback function that
  789.  *    is called whenever work becomes available for this controller. 
  790.  *    If the controller is not already busy we dequeue and start the
  791.  *    request.
  792.  *    NOTE: This routine is also called from Dev_SIIIntr to start the
  793.  *    next request after the previously one finishes.
  794.  *
  795.  * Results:
  796.  *    None.
  797.  *
  798.  * Side effects:
  799.  *    Request may be dequeue and submitted to the device. Request callback
  800.  *    function may be called.
  801.  *
  802.  *----------------------------------------------------------------------
  803.  */
  804.  
  805. static Boolean
  806. entryAvailProc(clientData, newRequestPtr) 
  807.    ClientData    clientData;    /* Really the Device this request ready. */
  808.    List_Links    *newRequestPtr;    /* The new SCSI request. */
  809. {
  810.     register Device     *devPtr;
  811.     register Controller    *ctrlPtr;
  812.     register ScsiCmd    *scsiCmdPtr;
  813.     ReturnStatus    status;
  814.  
  815.     static Address    notifications[100];
  816.     static Address    sent[100];
  817.     static Address    bailed[100];
  818.     static Address    cause[100];
  819.     static Address    failed[100];
  820.     static int        nctr = 0;
  821.     static int        sctr = 0;
  822.     static int        bctr = 0;
  823.     static int        fctr = 0;
  824. #define INC(a) { (a) = ((a) + 1) % 100; }
  825.  
  826.     devPtr = (Device *) clientData;
  827.     ctrlPtr = devPtr->ctrlPtr;
  828.     /*
  829.      * If we are busy (have an active request) just return. Otherwise 
  830.      * start the request.
  831.      */
  832.  
  833.     notifications[nctr] = (Address) newRequestPtr;
  834.     INC(nctr);
  835.     if (ctrlPtr->scsiCmdPtr != (ScsiCmd *) NIL) {
  836.     bailed[bctr] = (Address) newRequestPtr;
  837.     cause[bctr] = (Address) ctrlPtr->scsiCmdPtr;
  838.     INC(bctr);
  839.     return FALSE;
  840.     }
  841. again:
  842.     scsiCmdPtr = (ScsiCmd *) newRequestPtr;
  843.     devPtr = (Device *) clientData;
  844.     sent[sctr] = (Address) scsiCmdPtr;
  845.     INC(sctr);
  846.     status = SendCommand((Device *) devPtr, scsiCmdPtr);
  847.     /*    
  848.      * If the command couldn't be started do the callback function.
  849.      */
  850.     if (status != SUCCESS) {
  851.     failed[fctr] = (Address) scsiCmdPtr;
  852.     INC(fctr);
  853.      MASTER_UNLOCK(&(ctrlPtr->mutex));
  854.      RequestDone(devPtr,scsiCmdPtr,status,0,0);
  855.      MASTER_LOCK(&(ctrlPtr->mutex));
  856.     }
  857.     if (ctrlPtr->scsiCmdPtr == (ScsiCmd *) NIL) {
  858.         newRequestPtr = Dev_QueueGetNextFromSet(ctrlPtr->devQueues,
  859.                                 DEV_QUEUE_ANY_QUEUE_MASK,&clientData);
  860.         if (newRequestPtr != (List_Links *) NIL) {
  861.             goto again;
  862.         }
  863.     }
  864.     return TRUE;
  865.  
  866. }   
  867.  
  868.  
  869. /*
  870.  *----------------------------------------------------------------------
  871.  *
  872.  * Dev_SIIIntr --
  873.  *
  874.  *    Handle interrupts from the SII controller.
  875.  *
  876.  * Results:
  877.  *    TRUE if an SII controller was responsible for the interrupt
  878.  *    and this routine handled it.
  879.  *
  880.  * Side effects:
  881.  *    Usually a process is notified that an I/O has completed.
  882.  *
  883.  *----------------------------------------------------------------------
  884.  */
  885. Boolean
  886. Dev_SIIIntr()
  887. {
  888.     Controller            *ctrlPtr;
  889.     volatile register SIIRegs    *regsPtr;
  890.     Device            *devPtr;
  891.     unsigned char        statusByte = 0;
  892.     ReturnStatus        status;
  893.     register int        i;
  894.     Boolean            found;
  895.     List_Links            *newRequestPtr;
  896.     ClientData            clientData;
  897.     unsigned short        cstat;
  898.     unsigned short        dstat;
  899.  
  900.     if (devSIIDebug > 4) {
  901.     printf("DevSIIIntr: ");
  902.     }
  903.     found = FALSE;
  904.     /*
  905.      * Find which controller caused the interrupt.
  906.      */
  907.     for (i = 0; i < numSIIControllers; i++) {
  908.     ctrlPtr = controllers[i];
  909.     if (ctrlPtr == (Controller *) 0) {
  910.         continue;
  911.     }
  912.     regsPtr = (SIIRegs *)ctrlPtr->regsPtr;
  913.     devPtr = ctrlPtr->devPtr;
  914.     cstat = regsPtr->cstat;
  915.     dstat = regsPtr->dstat;
  916.     if (cstat & (SII_CI | SII_DI)) {
  917.         found = TRUE;
  918.         break;
  919.     }
  920.     }
  921.     if (!found) {
  922.     if (devSIIDebug > 4 ) {
  923.         printf("spurious\n");
  924.     }
  925.     return FALSE;
  926.     }
  927.  
  928.     /*
  929.      * Acknowledge everything.
  930.      */
  931.     regsPtr->cstat = cstat;
  932.     regsPtr->dstat = dstat;
  933.     Mach_EmptyWriteBuffer();
  934.  
  935.     /*
  936.      * Check for a BUS ERROR
  937.      */
  938.     if(cstat & SII_BER) {
  939.     if (devSIIDebug > 4) {
  940.         printf("Bus error");
  941.     }
  942.     }
  943.  
  944.     /*
  945.      * Check for a PARITY ERROR
  946.      */
  947.     if(dstat & SII_IPE) {
  948.     printf("Dev_SIIIntr: Parity error!!\n");
  949.     goto rtnHardErrorAndGetNext;
  950.     }
  951.  
  952.     /* 
  953.      * Check for a BUS RESET
  954.      */
  955.     if(cstat & SII_RST_ONBUS) {
  956.     printf("Dev_SIIIntr: Bus reset!!\n");
  957.     goto rtnHardErrorAndGetNext;
  958.     }
  959.  
  960.     /*
  961.      * Check for a state change.
  962.      */
  963.     if (cstat & SII_SCH) {
  964.     if (devSIIDebug > 4) {
  965.         printf("State change ");
  966.     }
  967.     }
  968.  
  969.     /*
  970.      * Check for DMA completion.
  971.      */
  972.     if (dstat & SII_DNE) {
  973.     if (devSIIDebug > 4) {
  974.         printf("DMA complete ");
  975.     }
  976.     }
  977.  
  978.     /*
  979.      * Check for phase change.
  980.      */
  981.     if (dstat & SII_MIS) {
  982.     if (devSIIDebug > 4) {
  983.         printf("Phase change ");
  984.     }
  985.     switch (dstat & SII_PHA_MSK) {
  986.         case DATA_IN_PHASE:
  987.         case DATA_OUT_PHASE: {
  988.         if (devSIIDebug > 4) {
  989.             printf("Data Phase Interrupt\n");
  990.         }
  991.         status = StartDMA(ctrlPtr, ctrlPtr->dmaState, FALSE, 
  992.             ctrlPtr->scsiCmdPtr->bufferLen, 
  993.             ctrlPtr->scsiCmdPtr->buffer);
  994.         if (status != SUCCESS) {
  995.             printf("Warning: couldn't start dma.\n");
  996.         }
  997.         return(TRUE);
  998.         }
  999.         case MSG_IN_PHASE: {
  1000.         char    message;
  1001.         status = StartDMA(ctrlPtr, DMA_RECEIVE, TRUE, 1, &message);
  1002.         if (devSIIDebug > 4) {
  1003.             printf("Msg Phase Interrupt\n");
  1004.         }
  1005.         if (status != SUCCESS) {
  1006.             printf("Warning: %s couldn't get message.\n",ctrlPtr->name);
  1007.             return(TRUE);
  1008.         }
  1009.         if (message != SCSI_COMMAND_COMPLETE) {
  1010.             printf("Warning: %s couldn't handle message 0x%x from %s.\n",
  1011.                 ctrlPtr->name, message, 
  1012.                 ctrlPtr->devPtr->handle.locationName);
  1013.         }
  1014.         return(TRUE);
  1015.         }
  1016.         case STATUS_PHASE: {
  1017.         if (devSIIDebug > 4) {
  1018.             printf("Status Phase Interrupt\n");
  1019.         }
  1020.         if ((ctrlPtr->dmaStarted == TRUE) && 
  1021.             (ctrlPtr->dmaState == DMA_RECEIVE)) {
  1022.             /*
  1023.              * We just transitioned from the data phase so copy
  1024.              * in the data.
  1025.              */
  1026.             CopyFromBuffer((unsigned short *)(ctrlPtr->ramBuff + 
  1027.                               devPtr->buffOffset),
  1028.                    (unsigned char *)ctrlPtr->scsiCmdPtr->buffer,
  1029.            (int)(ctrlPtr->scsiCmdPtr->bufferLen - regsPtr->dmlotc));
  1030.            ctrlPtr->dmaStarted = FALSE;
  1031.         }
  1032.     
  1033.         status =  GetStatusByte(ctrlPtr, &statusByte);
  1034.         if (status != SUCCESS) {
  1035.                         /* Return the hard error message
  1036.                          * to the call and get the next 
  1037.                          * entry in the devQueue. */
  1038.             goto rtnHardErrorAndGetNext;
  1039.         }
  1040.         RequestDone(devPtr, ctrlPtr->scsiCmdPtr, status, statusByte,
  1041.             (int)(ctrlPtr->scsiCmdPtr->bufferLen - regsPtr->dmlotc));
  1042.         if (ctrlPtr->scsiCmdPtr == (ScsiCmd *)NIL) {
  1043.             newRequestPtr = Dev_QueueGetNextFromSet(ctrlPtr->devQueues,
  1044.                     DEV_QUEUE_ANY_QUEUE_MASK,&clientData);
  1045.             if (newRequestPtr != (List_Links *) NIL) { 
  1046.             MASTER_LOCK(&(ctrlPtr->mutex));
  1047.             entryAvailProc(clientData,newRequestPtr);
  1048.             MASTER_UNLOCK(&(ctrlPtr->mutex));
  1049.             }
  1050.         }
  1051.         return(TRUE);
  1052.         }
  1053.         default: {
  1054.         printf("Warning: %s couldn't handle phase %x... ignoring.\n",
  1055.                ctrlPtr->name, dstat & SII_PHA_MSK);
  1056.         if (devSIIDebug > 0) {
  1057.             PrintRegs(regsPtr);
  1058.         }
  1059.         return(TRUE);
  1060.         }
  1061.     }
  1062.     }
  1063.     if (devSIIDebug > 4) {
  1064.     printf("\n");
  1065.     }
  1066.  
  1067.     return(TRUE);
  1068.  
  1069.     /*
  1070.      * Jump here to return an error and reset the HBA.
  1071.      */
  1072. rtnHardErrorAndGetNext:
  1073.     printf("Warning: %s reset and current command terminated.\n",
  1074.        devPtr->handle.locationName);
  1075.     if (ctrlPtr->scsiCmdPtr != (ScsiCmd *) NIL) {
  1076.     RequestDone(devPtr,ctrlPtr->scsiCmdPtr,status,statusByte,0);
  1077.     }
  1078.     Reset(ctrlPtr);
  1079.     /*
  1080.      * Use the queue entryAvailProc to start the next request for this device.
  1081.      */
  1082.     newRequestPtr = Dev_QueueGetNextFromSet(ctrlPtr->devQueues,
  1083.                 DEV_QUEUE_ANY_QUEUE_MASK,&clientData);
  1084.     if (newRequestPtr != (List_Links *) NIL) { 
  1085.     MASTER_LOCK(&(ctrlPtr->mutex));
  1086.     entryAvailProc(clientData,newRequestPtr);
  1087.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1088.     }
  1089.     return (TRUE);
  1090.  
  1091. }
  1092.  
  1093. /*
  1094.  *----------------------------------------------------------------------
  1095.  *
  1096.  * ReleaseProc --
  1097.  *
  1098.  *    Device release proc for controller.
  1099.  *
  1100.  * Results:
  1101.  *    None.
  1102.  *
  1103.  * Side effects:
  1104.  *    None.
  1105.  *
  1106.  *----------------------------------------------------------------------
  1107.  */
  1108. /*ARGSUSED*/
  1109. static ReturnStatus
  1110. ReleaseProc(scsiDevicePtr)
  1111.     ScsiDevice    *scsiDevicePtr;
  1112. {
  1113.  
  1114. }
  1115.  
  1116.  
  1117. /*
  1118.  *----------------------------------------------------------------------
  1119.  *
  1120.  * DevSIIInit --
  1121.  *
  1122.  *    Check for the existant of the SII controller. If it
  1123.  *    exists allocate data stuctures for it.
  1124.  *
  1125.  * Results:
  1126.  *    TRUE if the controller exists, FALSE otherwise.
  1127.  *
  1128.  * Side effects:
  1129.  *    Memory may be allocated.
  1130.  *
  1131.  *----------------------------------------------------------------------
  1132.  */
  1133. ClientData
  1134. DevSIIInit(ctrlLocPtr)
  1135.     DevConfigController    *ctrlLocPtr;    /* Controller location. */
  1136. {
  1137.     int        ctrlNum;
  1138.     Controller *ctrlPtr;
  1139.     int        i,j;
  1140.  
  1141.     ctrlNum = ctrlLocPtr->controllerID;
  1142.     /*
  1143.      * It's there. Allocate and fill in the Controller structure.
  1144.      */
  1145.     if (ctrlNum+1 > numSIIControllers) {
  1146.     numSIIControllers = ctrlNum + 1;
  1147.     }
  1148.     controllers[ctrlNum] = ctrlPtr = (Controller *) malloc(sizeof(Controller));
  1149.     bzero((char *) ctrlPtr, sizeof(Controller));
  1150.     ctrlPtr->regsPtr = (SIIRegs *) (ctrlLocPtr->address);
  1151.     ctrlPtr->ramBuff = SII_BUF_BASE;
  1152.     ctrlPtr->name = ctrlLocPtr->name;
  1153.     Sync_SemInitDynamic(&(ctrlPtr->mutex),ctrlPtr->name);
  1154.     /* 
  1155.      * Initialized the name, device queue header, and the master lock.
  1156.      * The controller comes up with no devices active and no devices
  1157.      * attached.  Reserved the devices associated with the 
  1158.      * targetID of the controller (7).
  1159.      */
  1160.     ctrlPtr->devQueues = Dev_CtrlQueuesCreate(&(ctrlPtr->mutex),entryAvailProc);
  1161.     for (i = 0; i < 8; i++) {
  1162.     for (j = 0; j < 8; j++) {
  1163.         ctrlPtr->devicePtr[i][j] = (i == 7) ? (Device *) 0 : (Device *) NIL;
  1164.     }
  1165.     }
  1166.     ctrlPtr->scsiCmdPtr = (ScsiCmd *) NIL;
  1167.     Reset(ctrlPtr);
  1168.     return((ClientData) ctrlPtr);
  1169. }
  1170.  
  1171. /*
  1172.  * Offset into DMA buffer. We partition the DMA buffer into seperate 
  1173.  * regions for each device.  We have to have seperate regions if we
  1174.  * ever want disconnect/reconnect.
  1175.  *
  1176.  * IMPORTANT!!!
  1177.  * For some reason DMA doesn't work if this offset is anything other than
  1178.  * 0. Do not increment it when attaching devices.
  1179.  */
  1180.  
  1181. static unsigned ramBuffOffset = 0;
  1182.  
  1183.  
  1184. /*
  1185.  *----------------------------------------------------------------------
  1186.  *
  1187.  * DevSIIDevice --
  1188.  *
  1189.  *    Attach a SCSI device using the SII HBA.
  1190.  *
  1191.  * Results:
  1192.  *    None.
  1193.  *
  1194.  * Side effects:
  1195.  *    None.
  1196.  *
  1197.  *----------------------------------------------------------------------
  1198.  */
  1199.  
  1200. ScsiDevice   *
  1201. DevSIIAttachDevice(devicePtr, insertProc)
  1202.     Fs_Device    *devicePtr;     /* Device to attach. */
  1203.     void    (*insertProc)(); /* Queue insert procedure. */
  1204. {
  1205.     Device        *devPtr;
  1206.     Controller        *ctrlPtr;
  1207.     char           tmpBuffer[512];
  1208.     int               length;
  1209.     int               ctrlNum;
  1210.     int               targetID, lun;
  1211.     extern char        *strcpy();
  1212.  
  1213.     /*
  1214.      * First find the SII controller this device is on.
  1215.      */
  1216.     ctrlNum = SCSI_HBA_NUMBER(devicePtr);
  1217.     if ((ctrlNum > MAX_SII_CTRLS) ||
  1218.     (controllers[ctrlNum] == (Controller *) 0)) { 
  1219.     return (ScsiDevice  *) NIL;
  1220.     } 
  1221.     ctrlPtr = controllers[ctrlNum];
  1222.     /*
  1223.      * See if the device is already present.
  1224.      */
  1225.     targetID = SCSI_TARGET_ID(devicePtr);
  1226.     lun = SCSI_LUN(devicePtr);
  1227.     MASTER_LOCK(&(ctrlPtr->mutex));
  1228.  
  1229.     /*
  1230.      * A device pointer of zero means that targetID/LUN 
  1231.      * conflicts with that of the HBA. A NIL means the
  1232.      * device hasn't been attached yet.
  1233.      */
  1234.     if (ctrlPtr->devicePtr[targetID][lun] == (Device *) 0) {
  1235.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1236.     return (ScsiDevice *) NIL;
  1237.     }
  1238.     if (ctrlPtr->devicePtr[targetID][lun] != (Device *) NIL) {
  1239.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1240.     return (ScsiDevice *) (ctrlPtr->devicePtr[targetID][lun]);
  1241.     }
  1242.  
  1243.     /*
  1244.      * Initialize the device struct.
  1245.      */
  1246.     devPtr = (Device *) malloc(sizeof(Device));
  1247.     bzero((char *) devPtr, sizeof(Device));
  1248.     devPtr->targetID = targetID;
  1249.     devPtr->ctrlPtr = ctrlPtr;
  1250.     devPtr->buffOffset = ramBuffOffset;
  1251.     ctrlPtr->devPtr = (Device *)NIL;
  1252.     ctrlPtr->scsiCmdPtr = (ScsiCmd *)NIL;
  1253.     ctrlPtr->devicePtr[targetID][lun] = devPtr;
  1254.     /*
  1255.      * Until we support disconnect/reconnect all device queues are
  1256.      * stored under the same queueBit
  1257.      */
  1258.     devPtr->handle.devQueue = Dev_QueueCreate(ctrlPtr->devQueues,
  1259.                 1, insertProc, (ClientData) devPtr);
  1260.     devPtr->handle.releaseProc = ReleaseProc;
  1261.     devPtr->handle.LUN = lun;
  1262.     devPtr->handle.maxTransferSize = SII_MAX_DMA_XFER_LENGTH;
  1263.     (void) sprintf(tmpBuffer, "%s#%d Target %d LUN %d", ctrlPtr->name, ctrlNum,
  1264.             devPtr->targetID, devPtr->handle.LUN);
  1265.     length = strlen(tmpBuffer);
  1266.     devPtr->handle.locationName = (char *) strcpy(malloc(length+1),tmpBuffer);
  1267.  
  1268.     /*
  1269.      * IMPORTANT: the following statement is ifdef'd out for a reason.
  1270.      * See comment above.
  1271.      */
  1272. #if 0
  1273.     ramBuffOffset += SII_MAX_DMA_XFER_LENGTH * 2;
  1274. #endif
  1275.  
  1276.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1277.     return (ScsiDevice *) devPtr;
  1278. }
  1279.  
  1280.  
  1281.  
  1282. /*
  1283.  *----------------------------------------------------------------------
  1284.  *
  1285.  * CopyToBuffer --
  1286.  *
  1287.  *    Copy data to the dma buffer. The dma buffer can only be written
  1288.  *    one word at a time.
  1289.  *
  1290.  * Results:
  1291.  *    None.
  1292.  *
  1293.  * Side effects:
  1294.  *    None.
  1295.  *
  1296.  *----------------------------------------------------------------------
  1297.  */
  1298. CopyToBuffer(src, dst, length)
  1299.     register volatile unsigned short    *src;
  1300.     register volatile unsigned short    *dst;
  1301.     register int             length;
  1302. {
  1303.     while(length > 0) {
  1304.     *dst++ = *src++;
  1305.     dst++;
  1306.     length -= 2;
  1307.     }
  1308. }
  1309.  
  1310.  
  1311. /*
  1312.  *----------------------------------------------------------------------
  1313.  *
  1314.  * CopyFromBuffer --
  1315.  *
  1316.  *    Copy data from the dma buffer. The dma buffer can only be read
  1317.  *    one word at a time.
  1318.  *
  1319.  * Results:
  1320.  *    None.
  1321.  *
  1322.  * Side effects:
  1323.  *    None.
  1324.  *
  1325.  *----------------------------------------------------------------------
  1326.  */
  1327. CopyFromBuffer(src, dst, length)
  1328.     volatile register unsigned short    *src;
  1329.     volatile register unsigned char    *dst;
  1330.     register int            length;
  1331. {
  1332.     if((int)dst & 0x01) {
  1333.     while(length > 1) {
  1334.         *dst++ = *src & 0xff;
  1335.         *dst++ = (*src >> 8) & 0xff;
  1336.         src += 2;
  1337.         length -= 2;
  1338.     }
  1339.     if (length == 1) {
  1340.         /*
  1341.          * Handle an odd length.  Shove the last byte out.
  1342.          */
  1343.         *dst = *src & 0xff;
  1344.     }
  1345.     } else {
  1346.     register unsigned short *wdst = (unsigned short *)dst;
  1347.     register int        i;
  1348.  
  1349.     for(i = 0; i<length-16; i+=16) {
  1350.         *wdst = *src;
  1351.         *(wdst+1) = *(src+2);
  1352.         *(wdst+2) = *(src+4);
  1353.         *(wdst+3) = *(src+6);
  1354.  
  1355.         *(wdst+4) = *(src+8);
  1356.         *(wdst+5) = *(src+10);
  1357.         *(wdst+6) = *(src+12);
  1358.         *(wdst+7) = *(src+14);
  1359.         src += 16;
  1360.         wdst += 8;
  1361.     }
  1362.     while(i < length - 1) {
  1363.         *wdst++ = *src;
  1364.         src += 2;
  1365.         i += 2;
  1366.     }
  1367.     if (i == length - 1) {
  1368.         /*
  1369.          * Handle an odd length.  Shove the last byte out.
  1370.          */
  1371.         *dst = *src & 0xff;
  1372.     }
  1373.     }
  1374. }
  1375.